home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / hips / sources / scale_geom / scanline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-17  |  6.2 KB  |  285 lines

  1. /*
  2.  * scanline: package of generic scanline operations
  3.  * Performs various filtering operations on scanlines of pixels.
  4.  * black&white or color, at 1, 2, or 4 bytes per pixel.
  5.  * Operations are currently implemented for only a subset of the possible data
  6.  * type combinations.
  7.  *
  8.  * Paul Heckbert    12 Sept 1988
  9.  */
  10.  
  11. static char rcsid[] = "$Header: scanline.c,v 3.0 88/10/10 13:51:11 ph Locked $";
  12. #include <stdio.h>
  13.  
  14. #include "simple.h"
  15. #include "pic.h"
  16. #include "scanline.h"
  17.  
  18. /* some machines/compilers don't do unsigned chars correctly (PDP 11's) */
  19. /* #define BAD_UCHAR /* define this if your machine has bad uchars */
  20. #ifdef BAD_UCHAR
  21. #   define UCHAR(x) ((x)&255)
  22. #else
  23. #   define UCHAR(x) (x)
  24. #endif
  25.  
  26. #define BYTES(buf) ((buf)->type&PIXEL_BYTESMASK)
  27. #define CHAN(buf) ((buf)->type&PIXEL_CHANMASK)
  28. #define TYPECOMB(type1, type2) ((type1)<<3 | (type2))
  29. #define PEG(val, t) (t = (val), t < 0 ? 0 : t > CHANWHITE ? CHANWHITE : t)
  30.  
  31. #define YOU_LOSE(routine) { \
  32.     fprintf(stderr, "scanline_%s: bad scanline type: %d\n", \
  33.     routine, buf->type); \
  34.     exit(1); \
  35. }
  36.  
  37. #define YOU_BLEW_IT(routine) { \
  38.     fprintf(stderr, "scanline_%s: bad type combination: %d & %d\n", \
  39.     routine, abuf->type, bbuf->type); \
  40.     exit(1); \
  41. }
  42.  
  43. /*
  44.  * scanline_alloc: allocate memory for scanline buf of the given type and length
  45.  */
  46.  
  47. scanline_alloc(buf, type, len)
  48.     Scanline *buf;
  49.     int       type, len;
  50. {
  51.     buf->type = type;
  52.     buf->len = len;
  53.     switch (type) {
  54.     case PIXEL_MONO | PIXEL1:
  55.     ALLOC(buf->u.row1, Pixel1, len);
  56.     break;
  57.     case PIXEL_MONO | PIXEL2:
  58.     ALLOC(buf->u.row2, Pixel2, len);
  59.     break;
  60.     case PIXEL_MONO | PIXEL4:
  61.     ALLOC(buf->u.row4, Pixel4, len);
  62.     break;
  63.     default:
  64.     YOU_LOSE("alloc");
  65.     }
  66. }
  67.  
  68. /*
  69.  * scanline_free: free the memory used by buf (but not buf itself)
  70.  */
  71.  
  72. scanline_free(buf)
  73.     Scanline *buf;
  74. {
  75.     switch (buf->type) {
  76.     case PIXEL_MONO | PIXEL1:
  77.     free(buf->u.row1);
  78.     break;
  79.     case PIXEL_MONO | PIXEL2:
  80.     free(buf->u.row2);
  81.     break;
  82.     case PIXEL_MONO | PIXEL4:
  83.     free(buf->u.row4);
  84.     break;
  85.  
  86.     default:
  87.     YOU_LOSE("free");
  88.     }
  89. }
  90.  
  91. /*
  92.  * scanline_zero: zero a scanline
  93.  */
  94.  
  95. scanline_zero(buf)
  96.     Scanline *buf;
  97. {
  98.     switch (buf->type) {
  99.     case PIXEL_MONO | PIXEL4:
  100.     bzero(buf->u.row4, buf->len * sizeof(Pixel4));
  101.     break;
  102.     default:
  103.     YOU_LOSE("zero");
  104.     }
  105. }
  106.  
  107. /*
  108.  * scanline_read: read buf->len pixels into buf starting at (x0,y0) in picture p
  109.  */
  110.  
  111. scanline_read(p, x0, y0, buf)
  112.     Pic      *p;
  113.     int       x0, y0;
  114.     Scanline *buf;
  115. {
  116.     switch (buf->type) {
  117.     case PIXEL_MONO | PIXEL1:
  118.     pic_read_row(p, y0, x0, buf->len, buf->u.row1);
  119.     break;
  120.     default:
  121.     YOU_LOSE("read");
  122.     }
  123. }
  124.  
  125. /*
  126.  * scanline_write: write buf->len pixels from buf into pic p starting at (x0,y0)
  127.  */
  128.  
  129. scanline_write(p, x0, y0, buf)
  130.     Pic      *p;
  131.     int       x0, y0;
  132.     Scanline *buf;
  133. {
  134.     switch (buf->type) {
  135.     case PIXEL_MONO | PIXEL1:
  136.     pic_write_row(p, y0, x0, buf->len, buf->u.row1);
  137.     break;
  138.     default:
  139.     YOU_LOSE("write");
  140.     }
  141. }
  142.  
  143. /*
  144.  * scanline_filter: convolve abuf with the sampled filter in wtab,
  145.  * writing the result to bbuf after shifting down by shift bits
  146.  * length of arrays taken to be bbuf->len
  147.  *
  148.  * Note that the Pixel4->Pixel1 routines shift abuf down by 8 bits before
  149.  * multiplying, to avoid overflow.
  150.  */
  151.  
  152. scanline_filter(shift, wtab, abuf, bbuf)
  153.     int       shift;
  154.     Weighttab *wtab;
  155.     Scanline *abuf, *bbuf;
  156. {
  157.     switch (TYPECOMB(abuf->type, bbuf->type)) {
  158.     case TYPECOMB(PIXEL_MONO | PIXEL1, PIXEL_MONO | PIXEL2):
  159.     pixel12_filter(bbuf->len, shift, wtab, abuf->u.row1, bbuf->u.row2);
  160.     break;
  161.     case TYPECOMB(PIXEL_MONO | PIXEL4, PIXEL_MONO | PIXEL1):
  162.     pixel41_filter(bbuf->len, shift, wtab, abuf->u.row4, bbuf->u.row1);
  163.     break;
  164.     default:
  165.     YOU_BLEW_IT("filter");
  166.     }
  167. }
  168.  
  169. pixel12_filter(bn, shift, wtab, abuf, bbuf)
  170.     int       bn, shift;
  171.     Weighttab *wtab;
  172.     Pixel1   *abuf;
  173.     Pixel2   *bbuf;
  174. {
  175.     register int af, sum;
  176.     register Pixel1 *ap;
  177.     register short *wp;
  178.     int       b;
  179.  
  180.     for (b = 0; b < bn; b++, wtab++) {
  181.     /* start sum at 1<<shift-1 for rounding */
  182.     for (sum = 1 << shift - 1, wp = wtab->weight, ap = &abuf[wtab->i0],
  183.          af = wtab->i1 - wtab->i0; af > 0; af--)
  184.         sum += *wp++ * (short) UCHAR(*ap++);
  185.     *bbuf++ = sum >> shift;
  186.     }
  187. }
  188.  
  189. pixel41_filter(bn, shift, wtab, abuf, bbuf)
  190.     int       bn, shift;
  191.     Weighttab *wtab;
  192.     Pixel4   *abuf;
  193.     Pixel1   *bbuf;
  194. {
  195.     register int af, sum;
  196.     register Pixel4 *ap;
  197.     register short *wp;
  198.     int       t, b;
  199.  
  200.     for (b = 0; b < bn; b++, wtab++) {
  201.     /* start sum at 1<<shift-1 for rounding */
  202.     for (sum = 1 << shift - 1, wp = wtab->weight, ap = &abuf[wtab->i0],
  203.          af = wtab->i1 - wtab->i0; af > 0; af--)
  204.         sum += *wp++ * (short) (*ap++ >> CHANBITS);
  205.     *bbuf++ = PEG(sum >> shift, t);
  206.     }
  207. }
  208.  
  209.  
  210. /*
  211.  * scanline_accum: bbuf += weight*accum
  212.  * length of arrays taken to be bbuf->len
  213.  */
  214.  
  215. scanline_accum(weight, abuf, bbuf)
  216.     int       weight;
  217.     Scanline *abuf, *bbuf;
  218. {
  219.     if (weight == 0)
  220.     return;
  221.     if (BYTES(bbuf) != PIXEL4 || CHAN(abuf) != CHAN(bbuf))
  222.     YOU_BLEW_IT("accum");
  223.     switch (abuf->type) {
  224.     case PIXEL_MONO | PIXEL1:
  225.     pixel14_accum(bbuf->len, weight, abuf->u.row1, bbuf->u.row4);
  226.     break;
  227.     case PIXEL_MONO | PIXEL2:
  228.     pixel24_accum(bbuf->len, weight, abuf->u.row2, bbuf->u.row4);
  229.     break;
  230.     default:
  231.     YOU_BLEW_IT("accum");
  232.     }
  233. }
  234.  
  235. pixel14_accum(n, weight, buf, accum)
  236.     register int n, weight;
  237.     register Pixel1 *buf;
  238.     register Pixel4 *accum;
  239. {
  240.     for (; n > 0; n--)
  241.     *accum++ += (short) weight *(short) UCHAR(*buf++);
  242. }
  243.  
  244. pixel24_accum(n, weight, buf, accum)
  245.     register int n, weight;
  246.     register Pixel2 *buf;
  247.     register Pixel4 *accum;
  248. {
  249.     for (; n > 0; n--)
  250.     *accum++ += (short) weight **buf++;
  251. }
  252.  
  253.  
  254. /*
  255.  * scanline_shift: bbuf = abuf>>shift
  256.  * length of arrays taken to be bbuf->len
  257.  */
  258.  
  259. scanline_shift(shift, abuf, bbuf)
  260.     int       shift;
  261.     Scanline *abuf, *bbuf;
  262. {
  263.     if (BYTES(abuf) != PIXEL4 || BYTES(bbuf) != PIXEL1 || CHAN(abuf) != CHAN(bbuf))
  264.     YOU_BLEW_IT("shift");
  265.     switch (CHAN(abuf)) {
  266.     case PIXEL_MONO:
  267.     pixel41_shift(bbuf->len, shift, abuf->u.row4, bbuf->u.row1);
  268.     break;
  269.     default:
  270.     YOU_BLEW_IT("shift");
  271.     }
  272. }
  273.  
  274. pixel41_shift(n, shift, accum, bbuf)
  275.     register int n, shift;
  276.     register Pixel4 *accum;
  277.     register Pixel1 *bbuf;
  278. {
  279.     register int t, half;
  280.  
  281.     half = 1 << shift - 1;
  282.     for (; n > 0; n--)
  283.     *bbuf++ = PEG(*accum++ + half >> shift, t);
  284. }
  285.